#pragma once

/**
 * Epoller:封装epoll，对描述符I/O事件监控模块
 * epoll_create epoll_ctl epoll_wait
 */

#include "Channel.h"
#include "Logger.h"

#include <sys/epoll.h>

#include <unordered_map>

namespace devem {

#define EPOLL_CREATE_SIZE 128
#define EPOLL_WAIT_NUM 10

class Epoller {
private:
    void EpollCtl(Channel* channel, int op) {
        int fd = channel->Fd();
        struct epoll_event ee;
        ee.events = channel->Events();
        int ret = epoll_ctl(epfd_, op, fd, &ee);
    }

    bool HasChannel(int fd) {
        return channels_.find(fd) != channels_.end();  // true:find it
    }

public:
    Epoller() : evs(new struct epoll_event[EPOLL_WAIT_NUM]) {
        epfd_ = epoll_create(EPOLL_CREATE_SIZE);
        if (epfd_ < 0) {
            LOG_WARN("epoll create fail.");
            abort();
        }
    }

    void Wait(std::vector<Channel*>* active, int flag);

    // UpdateEvent:hash表中没有该channel，就添加；否则修改
    void UpdateEvent(Channel* channel) {
        int fd = channel->Fd();
        if (HasChannel(fd)) {
            EpollCtl(channel, EPOLL_CTL_MOD);
        } else {
            EpollCtl(channel, EPOLL_CTL_ADD);
            channels_.insert(std::make_pair(fd, channel));
        }
    }

    // RemoveEvent:删除该channel
    void RemoveEvent(Channel* channel) {
        int fd = channel->Fd();
        if (HasChannel(fd)) {
            EpollCtl(channel, EPOLL_CTL_DEL);
            channels_.erase(fd);
        } else {
            LOG_INFO("this channel[fd = %d] is not exist.", fd);
        }
    }

    ~Epoller() {}

private:
    int epfd_;
    struct epoll_event* evs;
    std::unordered_map<int, Channel*> channels_;
};
}  // namespace devem